package com.yamibuy.ec.resource.handler;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.IoUtil;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import com.yamibuy.ec.resource.aws.AwsS3Util;
import com.yamibuy.ec.resource.domain.ImageRule;
import com.yamibuy.ec.resource.domain.WatermarkRule;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.filters.Watermark;
import net.coobird.thumbnailator.geometry.Coordinate;
import net.coobird.thumbnailator.util.ThumbnailatorUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 图片处理
 *
 * @author: damon.li
 * @version: 2021年02月23日 8:33
 */
@Component
@Slf4j
public class ImageHandler implements RequestHandlerFlag<String> {

	/**
	 * 需要处理的图片格式
	 */
	private static final String handleImagePathReg = "(^(/\\w+)+/\\w{32}_(.+)\\.(jpg|png|webp|tiff|jpeg|bmp)$)|(^(/\\w+)+/\\w{32}\\.?(jpg|png|webp|tiff|jpeg|bmp)?$)|(^(/\\w+).+\\.(jpg|png|webp|tiff|jpeg|bmp)$)";

	@Resource
	private AwsS3Util awsS3Util;

	@Override
	public ByteArrayOutputStream handle(String requestKeyRule) throws Exception {
		log.debug("收到图片请求: {} ", requestKeyRule);
		ImageRule imageRule = new ImageRule(requestKeyRule);
		log.debug("图片请求参数：{}", imageRule.toString());
		String fileKey = imageRule.getFileKey();
		log.debug("图片路径：{}", fileKey);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		// 获取主图
		BufferedImage mainImage = awsS3Util.getImage(fileKey);
		String defaultImageType = awsS3Util.getImageType(mainImage);
		if (imageRule.needHandle()) {
			Thumbnails.Builder<BufferedImage> of = Thumbnails.of(mainImage);
			// 大小缩放
			if (imageRule.needHandleWidthHeight()) {
				of.size(imageRule.getWidth(), imageRule.getHeight());
			} else {
				of.size(mainImage.getWidth(), mainImage.getHeight());
			}

			// 截取图片
			if (imageRule.needHandleCut()) {
				// 截取不处理高度，计算要截取的位置
				BufferedImage sourceImg = of.asBufferedImage();
				int height = sourceImg.getHeight();
				Integer extractHeight = imageRule.getExtractHeight();
				Integer currPage = imageRule.getExtractPage();
				int totalPage = ((height - 1) / extractHeight);
				// y方向截取位置
				int[] imagePageInfo = getImagePageInfo(currPage, totalPage, height, extractHeight);
				of = Thumbnails.of(sourceImg).size(sourceImg.getWidth(), imagePageInfo[1]).crop(new Coordinate(0, -imagePageInfo[0]));
			}


			// 水印处理
			WatermarkRule watermarkRule = imageRule.getWatermarkRule();
			if (watermarkRule != null) {
				BufferedImage waterImage = awsS3Util.getImage(watermarkRule.getKey());
				BufferedImage water = Thumbnails.of(waterImage)
						.size(watermarkRule.getWidth(), watermarkRule.getHeight())
						.outputFormat("png")
						.asBufferedImage();
				Watermark watermark = new Watermark(watermarkRule.getWaterPositions(), water, watermarkRule.getAlpha());
				of.watermark(watermark);
			}

			// 输出格式
			if (imageRule.getFileType() != null) {
				boolean support = ThumbnailatorUtils.isSupportedOutputFormat(imageRule.getFileType());
				if (support) {
					of.outputFormat(imageRule.getFileType());
					of.outputQuality(1.0d);
				} else {
					of.outputFormat(defaultImageType);
				}
			}

			// 输出流
			of.toOutputStream(out);
		} else {
			ImgUtil.write(mainImage, defaultImageType, out);
		}
		return out;
	}

	/**
	 * 获取图片的分页y轴的像素信息
	 *
	 * @return
	 */
	private int[] getImagePageInfo(int currPage, int totalPage, int height, int pageSize) {
		// 0截取位置 1截取高度
		int[] sizeInfo = new int[2];
		sizeInfo[1] = pageSize;
		if (currPage < totalPage) {
			sizeInfo[0] = currPage * pageSize;
		} else {
			currPage = totalPage;
			// 最后一页，精确计算剩余的像素
			sizeInfo[0] = currPage * pageSize;
			sizeInfo[1] = height - sizeInfo[0];
		}

		return sizeInfo;
	}

	@Override
	public boolean flag(String path) {
		boolean matches = path.matches(handleImagePathReg);
		return matches;
	}

	@Override
	public RequestHandlerFlag responseHeader(ServletResponse servletResponse) {
		servletResponse.setContentType(MediaType.IMAGE_PNG_VALUE);
		servletResponse.setCharacterEncoding(Charset.defaultCharset().name());
		return this;
	}
}
